﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace grounding.nao.sensors
{
    public class SensorFrame : ISensorFrame
    {
        protected double[] data;
        protected ISensor sender;
        protected DateTime timestamp;

        #region Constructors
        /// <summary>
        /// Creates a <c>SensorFrame</c> object automatically timestamping it as DateTime.Now
        /// </summary>
        /// <param name="origin">Sensor that generated the <c>SensorFrame</c></param>
        /// <param name="frame">The data to fill the <c>SensorFrame</c> with</param>
        public SensorFrame(ISensor origin, List<double> frame) : this(origin, frame.ToArray()) { }
        /// <summary>
        /// Creates a <c>SensorFrame</c> object
        /// </summary>
        /// <param name="origin">Sensor that generated the <c>SensorFrame</c></param>
        /// <param name="frame">The data to fill the <c>SensorFrame</c> with</param>
        /// <param name="time">The time that this <c>SensorFrame</c> was generated</param>
        public SensorFrame(ISensor origin, List<double> frame, DateTime time) : this(origin, frame.ToArray(), time) { }
        /// <summary>
        /// Creates a <c>SensorFrame</c> object automatically timestamping it as DateTime.Now
        /// </summary>
        /// <param name="origin">Sensor that generated the <c>SensorFrame</c></param>
        /// <param name="frame">The data to fill the <c>SensorFrame</c> with</param>
        public SensorFrame(ISensor origin, double[] frame) : this(origin, frame, DateTime.Now) { }
        /// <summary>
        /// Creates a <c>SensorFrame</c> object
        /// </summary>
        /// <param name="origin">Sensor that generated the <c>SensorFrame</c></param>
        /// <param name="frame">The data to fill the <c>SensorFrame</c> with</param>
        /// <param name="time">The time that this <c>SensorFrame</c> was generated</param>
        public SensorFrame(ISensor origin, double[] frame, DateTime time)
        {
            sender = origin;
            data = frame;
            timestamp = time;
        }
        #endregion

        #region ISensorFrame Members

        public ISensor Sender { get { return sender; } }

        public DateTime Timestamp { get { return timestamp; } }

        public double this[int i] { get { return data[i]; } }

        public double[] ToArray() { return data; }

        #endregion

        #region ICollection<double> Members

        public void Add(double item) { throw new InvalidOperationException("SensorFrame is an immutable datastructure"); }

        public void Clear() { throw new InvalidOperationException("SensorFrame is an immutable datastructure"); }

        public bool Contains(double item) { return data.Contains(item); }

        public void CopyTo(double[] array, int arrayIndex) { data.CopyTo(array, arrayIndex); }

        public int Count { get { return data.Length; } }

        public bool IsReadOnly { get { return true; } }

        public bool Remove(double item) { throw new InvalidOperationException("SensorFrame is an immutable datastructure"); }

        #endregion

        #region IEnumerable<double> Members

        public IEnumerator<double> GetEnumerator()
        {
            return data.AsEnumerable().GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return data.GetEnumerator();
        }

        #endregion

        #region IFormattable Members

        public override string ToString() { return ToString("", CultureInfo.CurrentCulture); }
        public string ToString(string format, IFormatProvider formatProvider)
        {
            string retval = "[ ";
            for (int i = 0; i < data.Length; i++)
            {
                retval += string.Format("{0:.00,4}", data[i]);
                if (i != data.Length - 1)
                    retval += ", ";
            }
            return retval + " ]";
        }

        #endregion
    }
}
